/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thienloc.omap.controller;

import com.thienloc.omap.entity.BroadcastConfig;
import com.thienloc.omap.entity.Broadcast;
import com.thienloc.omap.entity.BroadcastTemp;
import com.thienloc.omap.entity.Prefix;
import com.thienloc.omap.service.broadcast.BroadcastManager;
import com.thienloc.omap.service.broadcast.BroadcastUnit;
import com.thienloc.omap.session.BroadcastFacade;
import com.thienloc.omap.session.BroadcastTempFacade;
import com.thienloc.omap.session.PrefixFacade;
import com.thienloc.omap.util.CommonUtil;
import com.thienloc.omap.util.Constant;
import com.thienloc.omap.util.JsfUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.component.UIComponent;
import org.primefaces.event.TabChangeEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author GiangLT
 */
@ManagedBean
@ApplicationScoped
public class TabViewBean extends BaseBean {

    @EJB
    private BroadcastFacade broadcastFacade;
    @EJB
    private BroadcastTempFacade broadcastTempFacade;
    @EJB
    private PrefixFacade prefixFacade;
    protected int numOfTab = 0;
    protected List<TabInfo> tabList = new ArrayList<TabInfo>();
    private int activeIndex = 0;
    private static final String IPC_MODULE_PREFIX = "broadcast_";
    private final Logger logger = LoggerFactory.getLogger(TabViewBean.class);

    @PostConstruct
    public void init() {
        Collection<BroadcastUnit> broadcastUnits = BroadcastManager.getInstance(broadcastFacade).getBroadcastUnitMap().values();
        for (BroadcastUnit broadcastUnit : broadcastUnits) {
            BroadcastConfig config = broadcastUnit.getConfig();
            List<Broadcast> waitingList = broadcastFacade.findByStatus("WAITING", config.getModuleName());

            if (!waitingList.isEmpty()) {
                TabInfo tabInfo = new TabInfo();
                tabInfo.setIpcModule(config.getModuleName());
                tabInfo.setBroadcastConfig(config);
                tabInfo.setShooting(true);
                numOfTab++;
                tabInfo.setIndex(numOfTab);

                long remain = Long.valueOf(config.getSpeed()) * waitingList.size();
                tabInfo.setRemainingTime(tabInfo.getTimeString(remain));
                tabInfo.setTitle(config.getModuleName().replace("broadcast_smsgate_", ""));

                tabInfo.setWaitingList(waitingList);
                tabList.add(tabInfo);
            } else {
                try {
                    BroadcastManager.getInstance(broadcastFacade).stopBroadcast(config.getModuleName());
                } catch (Exception ex) {
                    logger.error("[{}]: ", getUsername(), ex);
                }
            }
        }
    }

    public void addTab(String tabPrefix) {
        TabInfo tab = new TabInfo();
        tab.setIndex(numOfTab);
        tab.setTitle(tabPrefix + " " + numOfTab);
        tabList.add(tab);
        numOfTab++;

    }

    public void removeTab(String tabTitle) {
        for (int i = 0; i < tabList.size(); i++) {
            if (tabList.get(i).getTitle().equals(tabTitle)) {
                tabList.remove(i);
                break;
            }

        }
    }

    public List<TabInfo> getTabList() {
        return tabList;
    }

    public void setTabList(List<TabInfo> tabList) {
        this.tabList = tabList;
    }

    public int getNumOfTab() {
        return numOfTab;
    }

    public void setNumOfTab(int numOfTab) {
        this.numOfTab = numOfTab;
    }

    public int getActiveIndex() {
        return activeIndex;
    }

    public void setActiveIndex(int activeIndex) {
        this.activeIndex = activeIndex;
    }

    public void changeActiveIndex(TabChangeEvent event) {
        String activeTab = event.getTab().getId();
        activeIndex = 0;
        for (UIComponent comp : event.getTab().getParent().getChildren()) {
            if (comp.getId().equals(activeTab)) {
                break;
            }
            activeIndex++;
        }
    }

    public class TabInfo implements Serializable {

        private int index;
        private String title;
        private String ipcModule;
        private List<Broadcast> waitingList = new ArrayList<Broadcast>();
        private List<Broadcast> blackList = new ArrayList<Broadcast>();
        private List<String> invalidList = new ArrayList<String>();
        private List<Broadcast> initList = new ArrayList<Broadcast>();
        private String initListStr;
        private String content;
        private String remainingTime;
        private Boolean shooting = false;
        private BroadcastConfig broadcastConfig = new BroadcastConfig();
        private final Logger logger = LoggerFactory.getLogger(TabInfo.class);

        //<editor-fold defaultstate="collapsed" desc="Getter Setter">
        public String getIpcModule() {
            return ipcModule;
        }

        public void setIpcModule(String ipcModule) {
            this.ipcModule = ipcModule;
        }

        public Boolean getShooting() {
            return shooting;
        }

        public void setShooting(Boolean shooting) {
            this.shooting = shooting;
        }

        public String getInitListStr() {
            return initListStr;
        }

        public void setInitListStr(String initListStr) {
            this.initListStr = initListStr;
        }

        public BroadcastConfig getBroadcastConfig() {
            return broadcastConfig;
        }

        public void setBroadcastConfig(BroadcastConfig broadcastConfig) {
            this.broadcastConfig = broadcastConfig;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }

        public List<Broadcast> getInitList() {
            return initList;
        }

        public void setInitList(List<Broadcast> initList) {
            this.initList = initList;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public List<Broadcast> getBlackList() {
            return blackList;
        }

        public void setBlackList(List<Broadcast> blackList) {
            this.blackList = blackList;
        }

        public List<String> getInvalidList() {
            return invalidList;
        }

        public void setInvalidList(List<String> invalidList) {
            this.invalidList = invalidList;
        }

        public String getRemainingTime() {
            return remainingTime;
        }

        public void setRemainingTime(String remainingTime) {
            this.remainingTime = remainingTime;
        }

        public List<Broadcast> getWaitingList() {
            return waitingList;
        }

        public void setWaitingList(List<Broadcast> waitingList) {
            this.waitingList = waitingList;
        }
        //</editor-fold>

        public String getWaitingListString() {
            StringBuilder sb = new StringBuilder();
            for (Broadcast broadcast : waitingList) {
                sb.append(broadcast.getMsisdn());
                sb.append("\n");
            }
            return sb.toString();
        }

        public String getInvalidListString() {
            StringBuilder sb = new StringBuilder();
            for (String str : invalidList) {
                sb.append(str);
                sb.append("\n");
            }
            return sb.toString();
        }

        public void updateBroadcastStatus() {
            try {
                waitingList = broadcastFacade.findByStatus("WAITING", ipcModule);
                if (waitingList.isEmpty()) {
                    shooting = false;
//                    int toBeRemoved = -1;
//                    for (int i = 0; i < tabList.size(); i++) {
//                        if (tabList.get(i).getTitle().equals(this.title)) {
//                            tabList.remove(i);
//                            numOfTab--;
//                            break;
//                        }
//                    }
//
//                    if (toBeRemoved > -1) {
//                        for (int i = 0; i < tabList.size(); i++) {
//                            TabInfo tabInfo = tabList.get(i);
//                            int tabIndex = tabInfo.getIndex();
//                            if (tabIndex > toBeRemoved) {
//                                tabInfo.setIndex(tabIndex - 1);
//                            }
//                        }
//                    }
                    JsfUtil.addMessage(FacesMessage.SEVERITY_WARN, "Kết thúc quảng bá", "Quá trình quảng bá đã kết thúc");
                }
                long remain = waitingList.size() / Long.valueOf(broadcastConfig.getSpeed());
                remainingTime = getTimeString(remain);
            } catch (Exception ex) {
                logger.error("[{}]: ", getUsername(), ex);
            }
        }

        public void processList() {
            try {
                if (content.contains(";") || content.contains(";")) {
                    JsfUtil.addErrorMessage("Sai nội dung", "Nội dung tin nhắn không được chứa dấu ';' hoặc dấu '|'");
                    return;
                }

                ipcModule = IPC_MODULE_PREFIX + broadcastConfig.getOperator() + "_" + index;
                broadcastConfig.setModuleName(ipcModule);
                broadcastConfig.setSpeed(10);
                BroadcastManager.getInstance(broadcastFacade).addModule(broadcastConfig);

                String[] mdns = initListStr.split("\\r\\n");
                List<Prefix> prefixes = prefixFacade.findByOperator(broadcastConfig.getOperator().substring(8));
                List<String> strPrefixes = new ArrayList<String>(prefixes.size());
                for (Prefix prefix : prefixes) {
                    strPrefixes.add(prefix.getPrefix());
                }

                List<BroadcastTemp> validatedBroadcasts = new ArrayList<BroadcastTemp>();

                for (String mdn : mdns) {
                    //validate
                    String normalizedMdn = CommonUtil.normalizeMsisdn(mdn);
                    if (!strPrefixes.contains(CommonUtil.getPrefix(normalizedMdn))) {
                        invalidList.add(normalizedMdn);
                    } else {
                        //end validate

//                        Broadcast broadcast = broadcastFacade.findByMsisdn2Status(mdn, "COMPLETED", "WAITING");
//                        if (broadcast == null) {
                        BroadcastTemp broadcastTemp = new BroadcastTemp();
                        broadcastTemp.setContent(content);
                        broadcastTemp.setLastUpdateTime(new Date());
                        broadcastTemp.setMsisdn(normalizedMdn);
                        broadcastTemp.setStatus("WAITING");
                        broadcastTemp.setDestination(broadcastConfig.getOperator());
                        broadcastTemp.setIpcModule(broadcastConfig.getModuleName());
                        validatedBroadcasts.add(broadcastTemp);
//                        }
                    }
                }

                long start = System.currentTimeMillis();
                broadcastTempFacade.batchCreate(validatedBroadcasts);
                long end1 = System.currentTimeMillis();
                logger.info("[{}]:  Total filter time: {}", getUsername(), (end1 - start));

                int total = mdns.length;
                int loopRound = total / Constant.ORACLE_CURSOR_LENGTH + 1;
                for (int i = 0; i < loopRound; i++) {
                    broadcastTempFacade.moveDataToBroadcast(Constant.ORACLE_CURSOR_LENGTH);
                }

                long end2 = System.currentTimeMillis();
                logger.info("[{}]:  Total procedure time: {}", getUsername(), (end2 - start));

                updateBroadcastStatus();
//                waitingList = broadcastFacade.findByStatus("WAITING", ipcModule);
                this.title = ipcModule.replace("broadcast_smsgate_", "");
                this.initList.clear();
                this.initListStr = "";
                JsfUtil.addSuccessMessage("Thành công!", "Quá trình lọc danh sách đã hoàn thành");
            } catch (Exception ex) {
                logger.error("[{}]Failed to process list", getUsername(), ex);
            }
        }

        public void startBroadcast() {
            try {
                BroadcastManager broadcastManager = BroadcastManager.getInstance(broadcastFacade);
                broadcastManager.startBroadcast(broadcastConfig);
                shooting = true;

                JsfUtil.addSuccessMessage("Thành công!", "Quá trình quảng bá đã bắt đầu");
            } catch (Exception ex) {
                logger.error("[{}]: ", getUsername(), ex);
            }
        }

        public void stopBroadcast() {
            try {
                BroadcastManager broadcastManager = BroadcastManager.getInstance(broadcastFacade);
                broadcastManager.stopBroadcast(broadcastConfig.getModuleName());
                shooting = false;
            } catch (Exception ex) {
                logger.error("[{}]: ", getUsername(), ex);
            } finally {
//                int toBeRemoved = -1;
//                for (int i = 0; i < tabList.size(); i++) {
//                    if (tabList.get(i).getTitle().equals(this.title)) {
//                        tabList.remove(i);
//                        numOfTab--;
//                        break;
//                    }
//                }
//
//                if (toBeRemoved != -1) {
//                    for (int i = 0; i < tabList.size(); i++) {
//                        TabInfo tabInfo = tabList.get(i);
//                        int tabIndex = tabInfo.getIndex();
//                        if (tabIndex > toBeRemoved) {
//                            tabInfo.setIndex(tabIndex - 1);
//                        }
//                    }
//                }
                JsfUtil.addMessage(FacesMessage.SEVERITY_WARN, "Kết thúc quảng bá", "Quá trình quảng bá đã kết thúc");
            }
        }

        public void pauseBroadcast() {
            try {
                BroadcastManager broadcastManager = BroadcastManager.getInstance(broadcastFacade);
                broadcastManager.pauseBroadcast(broadcastConfig.getModuleName());
                shooting = false;
                JsfUtil.addSuccessMessage("Thành công!", "Quá trình quảng bá đã ngừng");
            } catch (Exception ex) {
                logger.error("[{}]: ", getUsername(), ex);
            }
        }

        public String getTimeString(Long timeInSeconds) {
            String format = String.format("%%0%dd", 2);
            String seconds = String.format(format, ((timeInSeconds % 3600) % 60));
            String minutes = String.format(format, (timeInSeconds % 3600) / 60);
            String hours = String.format(format, timeInSeconds / 3600);
            String result = hours + ":" + minutes + ":" + seconds;
            return result;
        }
    }
}
